package com.feizhaiyou.encrypt.codec;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.feizhaiyou.encrypt.constants.SecurityMode;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * @author ls
 */
@Data
@Slf4j
public class SM4Processor implements SecurityProcessor {

    private String secret;

    private SymmetricCrypto symmetricCrypto;

    public SM4Processor(String secret) {
        if (StringUtils.isBlank(secret)) {
            secret = generateKey();
            log.warn("SM4Processor is not configured with a secret, use randomly generated secret: {}", secret);
        }
        this.secret = secret;
        this.symmetricCrypto = SmUtil.sm4(SecureUtil.decode(secret));
    }

    @Override
    public byte[] decrypt(String text) {
        return symmetricCrypto.decrypt(text);
    }

    @Override
    public byte[] encrypt(byte[] data) {
        return symmetricCrypto.encrypt(data);
    }

    /**
     * 以base64编码生成SM4秘钥
     *
     * @return
     */
    public static String generateKey() {
        return generateKey(SecurityMode.BASE64);
    }

    /**
     * 生成SM4秘钥
     *
     * @param type {@link SecurityMode} 编码模式：hex，其他默认base64
     * @return
     */
    public static String generateKey(SecurityMode type) {
        byte[] keyBytes = SecureUtil.generateKey("SM4").getEncoded();
        switch (type) {
            case HEX:
                return HexUtil.encodeHexStr(keyBytes);
            case BASE64:
            default:
                return Base64Encoder.encode(keyBytes);
        }
    }


    public static void main(String[] args) {
        String secret = generateKey();
        System.out.println("secret = " + secret);
        SM4Processor sm4Processor = new SM4Processor("+6cuvzvyrFZpRG9pf3r7eQ==");
        byte[] encrypt = sm4Processor.encrypt("北京市东城区长安街".getBytes());
        String hexStr = Base64Encoder.encode(encrypt);
        System.out.println("decrypt = " + hexStr);
        byte[] decrypt = sm4Processor.decrypt("SSzrI9TBwQeFUf+RCoiyyA==");
        System.out.println("bytes = " + StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
    }
}
